package com.huangfu.learning.javabase.java.pattern.action.command;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/8/9
 * Time: 18:45
 * Version: 1.0
 * Description:命令模式：一种数据驱动的设计模式；请求以命令的形式包裹在对象中，并传给调用对象。调用对象寻找可以处理该命令的合适的对象，并把该命令传给相应的对象，该对象执行命令
 * https://blog.csdn.net/wwh578867817/article/details/51533263
 * <p>
 * 关键代码：定义三个角色：1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口
 * <p>
 * Client（客户）：负责创建一个具体的命令（Concrete Command）
 * Invoker（调用者）：调用者持有一个命令对象，并在某个时刻调用命令对象的 execute() 方法。
 * Command（命令接口）：包含命令对象的 execute() 方法和 undo() 方法。
 * ConcreteCommand（具体命令）：实现命令接口。包括两个操作，执行命令和撤销命令。
 * Receiver（接收者）：接受命令并执行。
 * <p>
 * 优点： 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
 * 缺点：使用命令模式可能会导致某些系统有过多的具体命令类。
 * <p>
 * 使用场景：认为是命令的地方都可以使用命令模式，比如： 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。
 **/
public class CommandPattern {

    //测试类
    public static void main(String[] args) {
        Invoker invoker=new Invoker();
        invoker.setCommand(new AddPageCommand());
        invoker.call();
    }
}

/**
 * Command 类
 */
interface Command {
    void execute();
}

/**
 * 新增一个页面的命令
 */
class AddPageCommand implements Command {
    /**
     * 项目经理
     */
    protected Projecter pm = new Projecter();

    /**
     * 产品经理
     */
    protected Product product = new Product();

    /**
     * UI
     */
    protected UI ui = new UI();

    /**
     * 码农实现
     */
    protected Code code = new Code();

    @Override
    public void execute() {
        System.out.println("******************接收指令********************");
        pm.getCommand();//项目经理收到指令
        product.getCommand();//产品经理收到指令
        ui.getCommand();//ui收到指令
        code.getCommand();//码农收到指令
        System.out.println("******************项目经理、产品经理添加需求并执行********************");
        pm.doAdd();
        product.doAdd();//添加
        pm.plan();
        product.plan();//执行
        System.out.println("******************UI、开发添加页面并执行********************");
        ui.doAdd();//添加
        ui.plan();//执行
        code.doAdd();//添加
        code.plan();//执行
        System.out.println("******************项目经理、产品经理验收********************");
        product.acceptance();
        pm.acceptance();
    }
}

/**
 * 抽象一个命令的执行者
 */
abstract class Group {

    /**
     * @Description: 得到命令
     */
    public abstract void getCommand();

    /**
     * @Description: 新增一个功能
     */
    public abstract void doAdd();

    /**
     * @Description: 减去一个功能
     */
    public abstract void doDel();

    /**
     * @Description: 开始实施
     */
    public abstract void plan();

}

/**
 * 执行者：UI妹子
 */
class UI extends Group {


    @Override
    public void getCommand() {
        System.out.println("UI收到命令");
    }

    @Override
    public void doAdd() {
        System.out.println("UI新增了一个页面");
    }

    @Override
    public void doDel() {
        System.out.println("UI去掉了一个页面");
    }

    @Override
    public void plan() {
        System.out.println("UI变更完毕");
    }
}

/**
 * 执行者：开发
 */
class Code extends Group {
    @Override
    public void getCommand() {
        System.out.println("开发收到命令");
    }

    @Override
    public void doAdd() {
        System.out.println("开发新写了一个页面");
    }

    @Override
    public void doDel() {
        System.out.println("开发注释了一个页面");
    }

    @Override
    public void plan() {
        System.out.println("开发变更完毕");
    }
}

/**
 * 执行者：产品经理
 */
class Product extends Group {
    @Override
    public void getCommand() {
        System.out.println("产品经理收到命令");
    }

    @Override
    public void doAdd() {
        System.out.println("产品经理新增了一个需求");
    }

    @Override
    public void doDel() {
        System.out.println("产品经理砍掉了一个需求");
    }

    @Override
    public void plan() {
        System.out.println("产品变更完毕");
    }

    public void acceptance() {
        System.out.println("产品经理验收");
    }
}

/**
 * 执行者：项目经理
 */
class Projecter extends Group {

    @Override
    public void getCommand() {
        System.out.println("项目经理讨论项目方案");
    }

    @Override
    public void doAdd() {
        System.out.println("批准项目");
    }

    @Override
    public void doDel() {
        System.out.println("重审项目");
    }

    @Override
    public void plan() {
        System.out.println("实施项目落地");
    }

    public void acceptance() {
        System.out.println("项目验收");
    }

}

/**
 * 负责人
 */
class Invoker {

    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void call() {
        this.command.execute();
    }
}